#include "coutputvideostream.h"

namespace buola { namespace media { namespace ffmpeg {

COutputVideoStream::COutputVideoStream(AVFormatContext* pCtx, const std::string& pCodec, const CSize_i& pSize)
{
    AVCodec *lCodec=avcodec_find_encoder_by_name(pCodec.c_str());
    
    mAV=avformat_new_stream(pCtx,lCodec);
    mAV->id=pCtx->nb_streams-1;
    
    //some parameters should probably be set here
    mAV->codec->pix_fmt=AV_PIX_FMT_YUV420P;
    mAV->codec->bit_rate=400000;
    mAV->codec->width=pSize.x;
    mAV->codec->height=pSize.y;
    mAV->codec->time_base.den=25;
    mAV->codec->time_base.num=1;
        
    if(pCtx->oformat->flags&AVFMT_GLOBALHEADER)
        mAV->codec->flags|=CODEC_FLAG_GLOBAL_HEADER;

    int lRet=avcodec_open2(mAV->codec,lCodec,nullptr);
    if(lRet<0) throw XInvalid("could not open video codec");
    
    mFrame=avcodec_alloc_frame();
    mConvert=nullptr;
    avpicture_alloc((AVPicture*)mFrame,mAV->codec->pix_fmt,mAV->codec->width,mAV->codec->height);
    mFrame->pts=0.0;
}

AVPacket *COutputVideoStream::EncodeImage(const img::CImage_rgb8& pImage)
{
    if(!mConvert)
    {
        mConvert=sws_getContext(pImage.Size().x,pImage.Size().y,PIX_FMT_RGB24,mAV->codec->width,mAV->codec->height,
                                mAV->codec->pix_fmt,SWS_BICUBIC,nullptr,nullptr,nullptr);
    }

    AVPicture lInPicture;
    avpicture_fill(&lInPicture,pImage.RawBytes(),PIX_FMT_RGB24,pImage.Size().x,pImage.Size().y);
    sws_scale(mConvert,lInPicture.data,lInPicture.linesize,0,pImage.Size().y,mFrame->data,mFrame->linesize);

    AVPacket *lPacket=new AVPacket;
    int lGotOutput;
    av_init_packet(lPacket);
    lPacket->data=nullptr;
    lPacket->size=0;
    
    int lRet=avcodec_encode_video2(mAV->codec,lPacket,mFrame,&lGotOutput);
    if(lRet<0) throw XInvalid("can't encode video frame");
    
    mFrame->pts+=av_rescale_q(1,mAV->codec->time_base,mAV->time_base);

    if(lGotOutput)
    {
        if(mAV->codec->coded_frame->key_frame)
            lPacket->flags|=AV_PKT_FLAG_KEY;
        lPacket->stream_index=mAV->index;
        
        return lPacket;
    }
    else
    {
        return nullptr;
    }
}

/*namespace ffmpeg*/ } /*namespace media*/ } /*namespace buola*/ }
